Skip to content

api: RETRO-2026-05-12 follow-ups — openapi for cached aggregates + agent_action on 401#24

Merged
mastermanas805 merged 1 commit into
masterfrom
retro-followups-2026-05-12
May 12, 2026
Merged

api: RETRO-2026-05-12 follow-ups — openapi for cached aggregates + agent_action on 401#24
mastermanas805 merged 1 commit into
masterfrom
retro-followups-2026-05-12

Conversation

@mastermanas805
Copy link
Copy Markdown
Member

Summary

Two small follow-up fixes flagged in the session retro doc:

Fix 1: OpenAPI documents the cached aggregate endpoints. The Wave 4-L endpoints GET /api/v1/billing/usage and GET /api/v1/team/summary were already live and tested in production, but /openapi.json had no path entries for them. Agents reading the spec alone had no machine-readable signal that the cached aggregates existed, so they were forced to scan the full /resources list to compute the same numbers the dashboard already had pre-aggregated. This PR adds:

  • Path entries with response examples + Cache-Control header documentation
  • BillingUsageResponse, TeamSummaryResponse, TeamSummaryResourceCounts, UsageMetric schemas
  • TestOpenAPI_CachedAggregateEndpointsDocumented guards both paths, schemas, and the Cache-Control header contract

Fix 2: agent_action surfaces on every middleware 401. middleware.RequireAuth was emitting the bare three-key 401 shape {ok:false, error:"unauthorized"} on auth rejection. Downstream handlers that go through respondError already emit the agent_action sentence for the "unauthorized" code (via codeToAgentAction in helpers.go), but middleware bypasses that helper to avoid a circular import. The fix inlines the same prose + login URL directly in a new respondUnauthorized helper so an agent inspecting any 401 from this API gets the same remediation guidance regardless of which layer rejected the request. Six new test cases in auth_agent_action_test.go cover every RequireAuth failure path (no header, malformed bearer, invalid JWT, wrong secret, expired JWT, bearer-only).

Test plan

  • make test-unit — all packages green locally
  • After merge: curl -sS https://api.instanode.dev/api/v1/resources | jq . returns agent_action + upgrade_url fields (was previously the bare three-key shape)
  • After merge: curl -sS https://api.instanode.dev/openapi.json | jq '.paths | keys[] | select(test("billing/usage|team/summary"))' lists both new paths

Notes

  • Fix 1's OpenAPI additions overlap with PR #(env-aware deployments branch) which also touched the same file with the same content. If that lands first, the openapi.go diff here will resolve to a no-op; the test + middleware changes are independent.
  • agent_action matches the "unauthorized" entry in handlers.codeToAgentAction verbatim, so handler-emitted 401s and middleware-emitted 401s now return identical prose.

🤖 Generated with Claude Code

…ent_action on 401

Two small fixes flagged in the session retro:

Fix 1: /openapi.json was missing entries for the Wave 4-L cached aggregate
endpoints — GET /api/v1/billing/usage and GET /api/v1/team/summary — that
were already live and tested in production. Agents reading the spec alone
had no machine-readable signal that the cached aggregates existed, so they
were forced to fall back to scanning the full /resources list to compute
the same numbers the dashboard already had pre-aggregated. Added path
entries with response examples, Cache-Control header documentation, and
BillingUsageResponse / TeamSummaryResponse / TeamSummaryResourceCounts /
UsageMetric schemas. New test
TestOpenAPI_CachedAggregateEndpointsDocumented guards both paths +
schemas + the Cache-Control header contract so a future cleanup doesn't
silently drop them.

Fix 2: middleware.RequireAuth was emitting the bare three-key 401 shape
{ok:false, error:"unauthorized"} on every auth rejection. Downstream
handlers that go through respondError already emit the agent_action
sentence for the "unauthorized" code (via codeToAgentAction in
helpers.go), but the middleware bypasses that helper to avoid a circular
import. The fix inlines the same prose + login URL directly in a new
respondUnauthorized helper so an agent inspecting any 401 from this API
gets the same remediation guidance regardless of which layer rejected
the request. Six new test cases in auth_agent_action_test.go cover every
RequireAuth failure path (no header, malformed bearer, invalid JWT,
wrong secret, expired JWT, bearer-only).

Verification after merge:
  curl -sS https://api.instanode.dev/api/v1/resources | jq .
should now return:
  {
    "ok": false,
    "error": "unauthorized",
    "agent_action": "The user's INSTANODE_TOKEN is invalid or expired...",
    "upgrade_url": "https://instanode.dev/login"
  }
instead of the prior bare three-key shape.

Test gate: make test-unit — all packages green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant